﻿using ICSharpCode.NRefactory.CSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ATTAR
{
    public class ECHOElements
    {
        private string scriptName;
        private SyntaxTree tree;

        public SyntaxTree Tree
        {
            get { return tree; }
        }

        public List<AstNode> UsingDeclarations
        {
            get { return GetNodesByType("UsingDeclaration"); }
        }

        public List<AstNode> NamespaceDeclarations
        {
            get { return GetNodesByType("NamespaceDeclaration"); }
        }

        public List<AstNode> TypeDeclarations
        {
            get { return GetNodesByType("TypeDeclaration"); }
        }

        public List<AstNode> MethodDeclarations
        {
            get { return GetNodesByType("MethodDeclaration"); }
        }

        public List<AstNode> Comments
        {
            get { return GetNodesByType("Comment"); }
        }

        public List<AstNode> PreProcessorDirectives
        {
            get { return GetNodesByType("PreProcessorDirective"); }
        }

        public List<AstNode> VariableDeclarationStatements
        {
            get { return GetNodesByType("VariableDeclarationStatement"); }
        }

        public List<AstNode> VariableInitializerStatements
        {
            get { return GetNodesByType("VariableInitializer"); }
        }

        public List<AstNode> LambdaExpressions
        {
            get { return GetNodesByType("LambdaExpression"); }
        }

        public List<AstNode> AssignmentExpressions
        {
            get { return GetNodesByType("AssignmentExpression"); }
        }

        public List<AstNode> AttributeSections
        {
            get { return GetNodesByType("AttributeSection"); }
        }

        public List<AstNode> TryCatchStatements
        {
            get { return GetNodesByType("TryCatchStatement"); }
        }

        public List<AstNode> ExpressionStatements
        {
            get { return GetNodesByType("ExpressionStatement"); }
        }

        public List<AstNode> IfElseStatements
        {
            get { return GetNodesByType("IfElseStatement"); }
        }

        public List<AstNode> WhileStatements
        {
            get { return GetNodesByType("WhileStatement"); }
        }

        public List<AstNode> ForStatements
        {
            get { return GetNodesByType("ForStatement"); }
        }

        public List<AstNode> ForEachStatements
        {
            get { return GetNodesByType("ForEachStatement"); }
        }

        public List<AstNode> SwitchStatements
        {
            get { return GetNodesByType("SwitchStatement"); }
        }

        public List<AstNode> Identifiers
        {
            get { return GetNodesByType("Identifier"); }
        }

        public List<AstNode> InvocationExpressions
        {
            get { return GetNodesByType("InvocationExpression"); }
        }

        public List<AstNode> TimeoutAttributes
        {
            get
            {
                List<AstNode> attributes = AttributeSections;

                var timeouts = from attribute in attributes
                               where attribute.GetText().Substring(0, 8).Equals("[Timeout")
                               select attribute;

                return timeouts.ToList<AstNode>();
            }
        }

        public List<AstNode> ConsoleWriteStatements
        {
            get
            {
                var consoleWriteStatements = from expression in ExpressionStatements
                                             where expression.GetText().Replace(" ", string.Empty).Contains("Console.WriteLine(") || expression.GetText().Replace(" ", string.Empty).Contains("Console.Write(")
                                             select expression;

                return consoleWriteStatements.ToList<AstNode>();
            }
        }

        public List<AstNode> ConsoleLogStatements
        {
            get
            {
                var consoleLogStatements = from expression in this.ExpressionStatements
                                           where expression.GetText().Replace(" ", string.Empty).Contains("Console.Log(")
                                           select expression;

                return consoleLogStatements.ToList<AstNode>();
            }
        }
        
        public List<AstNode> TestMethods
        {
            get
            {
                List<AstNode> methods = MethodDeclarations;

                var testMethods = from method in methods
                                  where method.Children.ToList()[0].GetText().Replace(" ", string.Empty).Substring(0, 6).Equals("[Test]") || method.Children.ToList()[0].GetText().Replace(" ", string.Empty).Substring(0, 6).Equals("[Test(")
                                  select method;

                return testMethods.ToList<AstNode>();
            }
        }

        public string ScriptName { get { return scriptName; } }

        public ECHOElements(string scriptName, SyntaxTree tree)
        {
            this.scriptName = scriptName;
            this.tree = tree;
        }

        public bool IsTestFixture()
        {
            List<AstNode> attributes = AttributeSections;

            var fixtureNode = from attribute in attributes
                              where attribute.GetText().Substring(0, 8).Equals("[TestFix")
                              select attribute;

            return fixtureNode.ToList().Count > 0;
        }

        private List<AstNode> GetNodesByType(string type)
        {
            List<AstNode> nodes;

            var collection = from node in tree.DescendantsAndSelf
                             where node.GetType().Name.Equals(type)
                             select node;

            nodes = collection.ToList<AstNode>();

            return nodes;
        }

        public string GetNamespace()
        {
            string testNamespace = this.NamespaceDeclarations[0].GetText().Substring(0, this.NamespaceDeclarations[0].GetText().IndexOf("\r")).Replace("namespace ", "");

            return testNamespace;
        }

        public string GetAuthor()
        {
            string author = "No Author Found";

            foreach (AstNode node in AttributeSections)
            {
                if (node.GetText().StartsWith("[Author"))
                {
                    int commaIndex = node.GetText().IndexOf(",");
                    int index;

                    if (commaIndex == -1) // no email
                    {
                        author = node.GetText().Substring(node.GetText().IndexOf("(") + 2, node.GetText().IndexOf("\"", 10) - node.GetText().IndexOf("(") - 3);
                    }
                    else
                    {
                        author = node.GetText().Substring(node.GetText().IndexOf("(") + 2, node.GetText().IndexOf(",") - node.GetText().IndexOf("(") - 3);
                    }

                    break;
                }
            }

            return author;
        }

        public string GetEmailAddress()
        {
            string email = "No Email Address Found";

            foreach (AstNode node in AttributeSections)
            {
                if (node.GetText().StartsWith("[Author"))
                {
                    if (node.GetText().IndexOf(",") == -1)
                        email = "";
                    else
                        email = node.GetText().Substring(node.GetText().IndexOf(",") + 3, node.GetText().IndexOf(")") - node.GetText().IndexOf(",") - 4);

                    break;
                }
            }

            return email;
        }

        public string GetJIRANumber()
        {
            string jira = "No JIRA Found";

            foreach (AstNode node in Comments)
            {
                if (node.GetText().Contains("Reason:"))
                {
                    if (node.GetText().IndexOf("ULTI-") != -1)
                    {
                        string str = node.GetText();
                        int temp = str.Length - str.IndexOf("ULTI-");
                        if (str.Substring(str.IndexOf("ULTI-")).IndexOf(" ") > 0)
                        {
                            temp = str.Substring(str.IndexOf("ULTI-")).IndexOf(" ");
                        }

                        jira = str.Substring(str.IndexOf("ULTI-"), temp);

                        break;
                    }
                }
            }

            return jira;
        }

        public int FindEndRegion(List<AstNode> nodeList, int i)
        {
            int x = i;

            while (!nodeList[i].GetText().StartsWith("#endregion"))
            {
                if (nodeList[i].GetText().StartsWith("#region"))
                {
                    i++;
                    x = FindEndRegion(nodeList, i);
                    i = x;
                }

                i++;
            }

            return i;
        }
    }
}
